﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Windows.Forms;

using iPhoneUI.Shell;
using iPhoneUI.Widgets;

namespace iPhoneUI
{
    public class Page : IWidgetOwner, IDisposable
    {
        private Bitmap m_backgroundImage;
        private Rectangle m_backgroundImageBounds;
        private Form m_owner;
        private bool m_dragNavigate;

        private DragState m_dragState = new DragState();

        public readonly IDictionary<string, Widget> Widgets = new Dictionary<string, Widget>();

        public event NavigationEventHandler Navigate;

        public Page()
        {
            DragNavigate = true;
        }

        public Form Owner
        {
            get
            {
                return m_owner;
            }
            set
            {
                Debug.Assert(value != null);
                m_owner = value;
                m_dragState.StartThreshold = m_owner.Width / 10; // don't start dragging until this amount of movement
                m_dragState.CommitThreshold = m_owner.Width / 2; // need to drag have of width before navigating
            }
        }

        public bool DragNavigate
        {
            get
            {
                return m_dragNavigate;
            }
            set
            {
                m_dragNavigate = value;
                if (m_dragNavigate)
                    m_dragState.ContraintAxis = DragAxis.Horizontal;  // vertical scrolling currently not supported for anything
                else
                    m_dragState.ContraintAxis = DragAxis.None;
            }
        }

        public Rectangle Bounds { get; set; }

        public byte BackgroundAlpha { get; set; }

        public string Name { get; set; }

        public IEnumerable<WidgetRefConfig> WidgetRefs { get; set; }

        public string NextPage { get; set; }

        public string PreviousPage { get; set; }
        
        public int Width
        {
            get
            {
                return Bounds.Width;
            }
        }

        public Bitmap BackgroundImage
        {
            get
            {
                return m_backgroundImage;
            }
            set
            {
                m_backgroundImage.SafeDispose();
                Debug.Assert(value != null);

                m_backgroundImage = value;
                m_backgroundImageBounds = new Rectangle(0, 0, m_backgroundImage.Width, m_backgroundImage.Height);
            }
        }

        public void GotoPage(string page)
        {
            OnNavigate(page);
        }

        public Size ScaleSize(Size size)
        {
            return ShellConfig.ScaleSize(size);
        }

        public int ScaleX(int x)
        {
            return ShellConfig.ScaleX(x);
        }

        public int ScaleY(int y)
        {
            return ShellConfig.ScaleY(y);
        }

        protected virtual void OnNavigate(string page)
        {
            if(Navigate != null && string.IsNullOrEmpty(page) == false)
                Navigate(this, new NavigationEventArgs(page));
        }

        public void Update(Rectangle rectangle)
        {
            m_owner.Invalidate(Rectangle.Intersect(rectangle, Bounds));    // only allow invalidating within the page bounds
        }

        public void OwnerMouseMove(int x, int y)
        {
            if (DragNavigate)
            {
                m_dragState.Move(x, y);
                m_owner.Invalidate(Bounds);
            }
            else
            {
                foreach (Widget b in Widgets.Values)
                    b.OwnerMouseMove(x, y);
            }
        }

        public void OwnerMouseDown(int x, int y)
        {
            m_dragState.Start(x, y);

            foreach (Widget b in Widgets.Values)
                b.OwnerMouseDown(x, y);
        }

        public void OwnerMouseUp(int x, int y)
        {
            if (m_dragState.Direction == DragDirection.Right)
                OnNavigate(PreviousPage);
            else if (m_dragState.Direction == DragDirection.Left)
                OnNavigate(NextPage);

            m_dragState.Reset();

            foreach (Widget b in Widgets.Values)
                b.OwnerMouseUp(x, y);
        }

        public void Draw(Graphics graphics, Rectangle clipBounds)
        {
            if (BackgroundAlpha < 255)
                graphics.AlphaBlend(BackgroundImage, BackgroundAlpha, clipBounds, BackgroundImage.ScaleSourceRectangle(m_owner.Bounds, clipBounds));
            else
                graphics.DrawImage(BackgroundImage, clipBounds, BackgroundImage.ScaleSourceRectangle(m_owner.Bounds, clipBounds), GraphicsUnit.Pixel);

            Canvas canvas = new Canvas(graphics, m_dragState.DragAxisDelta);
            foreach (Widget w in Widgets.Values)
                w.Draw(canvas, clipBounds);
        }

        public virtual void Suspend()
        {
            foreach (Widget w in Widgets.Values)
                w.Suspend();
        }

        public virtual void Resume()
        {
            foreach (Widget w in Widgets.Values)
                w.Resume();
        }

        public void Dispose()
        {
            m_backgroundImage.SafeDispose();

            Widgets.Values.DisposeAll();

            Widgets.Clear();                
        }
    }
}
